/*****************************************************************************
 *   Copyright 2005 Tim A Wang
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 ****************************************************************************/
package com.jb.web.application.configuration;

import com.jb.framework.PersistentManager;
import com.jb.framework.database.mysql.SqlPersistentManager;
import com.jb.framework.pm.JarPersistentManager;
import com.jb.util.ClassUtil;
import com.jb.web.application.ApplicationImpl;
import com.jb.web.context.WebContext;
import com.jb.web.model.ApplicationConfig;
import com.jb.web.util.FileBrowser;

import java.io.File;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;


/**
 * This is singleton to manage the configuration needed for JB software
 */
public class Config extends ConfigBean {
    public static final String CONFIG = "config";
    public static final String WEB_INF = "WEB-INF";
    public static long ONE_DAY = 24 * 3600 * 1000;
    static private Config mConfiguration = new Config();

    //loader used for system xsp files
    static private PersistentManager systemPM;
    private ConfigBean externalBean;

    //database configuration
    private DBConfig dbConfig = new DBConfig();

    //
    //appliation server, tomcat, oc4j, or jboss
    //
    private String applServer = "tomcat";

    //default application
    private String defaultApplication = "system";

    //defautl page name
    private String defaultPage = "login.xsp";
    private String eMailAddress = "anpwang@comcast.net";
    private String errorPage = "error.html";
    private String externalConfig;
    private String externalConfigId;
    private String persistentManagerName = SqlPersistentManager.class.getName();
    private String searchIndexLocation;
    private String googleDevKey;
    //security manager
    private String securityManager = "com.jb.web.session.DummySecurityManager";
    private String smtpAddress = "smtp.comcast.net";
    //
    //system top relative to web top
    //
    private String systemTop = WEB_INF + "/jb/apps/system";
    //templates, relative to appltop
    private String templateTop = "/jb/apps/system/template"; //file location 

    //web top directory
    private String webTop;
    private boolean deployed;
    private boolean loaded;
    private boolean personalizable = true;
    private int debugLevel;
    private long sessionTimeout = ONE_DAY;
    private String icon;

    //site level managed beans;
   // private List managedBeans=new ArrayList();
    
    private Config() {
        super.setId(CONFIG);
        dbConfig.setId("dbconfig");
    }

    public List getBeans() {
        return this.getChildren();
    }
    
    public void addBean(ManagedBeanDef def) {
        //make sure class exist
        if(ClassUtil.getClass(def.getClassName())!=null)
        {
            addChild(def);
            update();
        }
    }
    public void deleteBean(ManagedBeanDef def) {
        if(getChildren().indexOf(def)!=-1) {
            getChildren().remove(def);
            update();
        }
    }
    
    public void setApplServer(String appsServer) {
        this.applServer = appsServer;
    }

    public String getApplServer() {
        return applServer;
    }

    public String getApplicationTop() {
        return getApplTop() + File.separatorChar + "apps";
    }

    public String getConfigTop() {
        return getApplTop() + File.separatorChar + "config";
    }

    public String getConnectionUrl() {
        return dbConfig.getUrl();
    }

    public DBConfig getDBConfig() {
        return dbConfig;
    }

    public String getDatabaseDriverName() {
        return dbConfig.getDriverName();
    }

    public void setDebugLevel(int debugLevel) {
        this.debugLevel = debugLevel;
    }

    public int getDebugLevel() {
        return debugLevel;
    }

    public void setDefaultPage(String defaultPage) {
        if (defaultPage != null) {
            if (!defaultPage.endsWith(".xsp")) {
                defaultPage = defaultPage + ".xsp";
            }
            this.defaultPage = defaultPage;
        }
    }

    public String getDefaultPage() {
        return defaultPage;
    }

    public void setDeployed(boolean deployed) {
        this.deployed = deployed;
    }
    /**
     * Returns true if this configuration is deployed. 
     * @return true if this configuration is deployed.
     */
    public boolean isDeployed() {
        return deployed;
    }
  
  
    /**
     * Returns a list of applications for the context passed in.
     * @param ctx runtime context.
     * @return list of applications.
     */
    public List getApplications(WebContext ctx) {
        List applList = new ArrayList();
        //
        ApplicationImpl apps = (ApplicationImpl)ctx.getApplication();
        FileBrowser fileBrowser = new FileBrowser(apps.getConfiguration().getApplicationTop());
        fileBrowser.stepIn(null, "", "");

        for (Iterator iter = fileBrowser.getDirList().iterator(); 
             iter.hasNext(); ) {
            ApplicationConfig app = new ApplicationConfig();
            app.setId(iter.next().toString());
            app.setName(app.getId());
            app.setTitle(app.getId());
            app.load();
            applList.add(app);
        }
        return applList;
    }
    
    public void setEMailAddress(String eMailAddress) {
        this.eMailAddress = eMailAddress;
    }

    public String getEMailAddress() {
        return eMailAddress;
    }

    public void setErrorPage(String errorPage) {
        this.errorPage = errorPage;
    }

    public String getErrorPage() {
        return errorPage;
    }

    public ConfigBean getExternalBean() {
        if (((externalBean == null) || ((externalBean != null) && !externalBean.getId().equals(externalConfigId))) &&
                (externalConfig != null) && (externalConfig.length() > 0)) {
                externalBean = (ConfigBean) ClassUtil.createInstance(externalConfig);
                if(externalBean!=null)
                {
                    externalBean.setId(externalConfigId);
            
                    if (webTop != null) {
                        externalBean.load(webTop);
                    }
                }
        }

        return externalBean;
    }

    /**
     * Returns singleton instance of jb configuration.
     *
     * @return singleton instance.
     */
    public static Config getInstance() {
        return mConfiguration;
    }

    /**
     * Sets default application for the installation.
     *
     * @param defaultApplication
     */
    public void setDefaultApplication(String defaultApplication) {
        this.defaultApplication = defaultApplication;
    }

    public String getDefaultApplication() {
        return defaultApplication;
    }

    public void setExternalConfig(String externalConfig) {
        this.externalConfig = externalConfig;
    }

    public String getExternalConfig() {
        return externalConfig;
    }

    public void setExternalConfigId(String externalConfigId) {
        this.externalConfigId = externalConfigId;
    }

    public String getExternalConfigId() {
        return externalConfigId;
    }

    public boolean isLoaded() {
        return loaded;
    }

    public String getPassword() {
        return dbConfig.getPassword();
    }

    public void setPersistentManagerName(String persistentManagerName) {
        this.persistentManagerName = persistentManagerName;
    }

    public String getPersistentManagerName() {
        return persistentManagerName;
    }

    public void setPersonalizable(boolean personalizable) {
        this.personalizable = personalizable;
    }

    public boolean isPersonalizable() {
        return personalizable;
    }

    public void setSearchIndexLocation(String searchIndexLocation) {
        this.searchIndexLocation = searchIndexLocation;
    }

    public String getSearchIndexLocation() {
        return searchIndexLocation;
    }

    public void setSecurityManager(String securityManager) {
        this.securityManager = securityManager;
    }

    public String getSecurityManager() {
        return securityManager;
    }

    public void setSessionTimeout(long sessionTimeout) {
        this.sessionTimeout = sessionTimeout;
    }

    public long getSessionTimeout() {
        return sessionTimeout;
    }

    public void setSmtpAddress(String smtpAddress) {
        this.smtpAddress = smtpAddress;
    }

    public String getSmtpAddress() {
        return smtpAddress;
    }

    public PersistentManager getSystemPersistentManager() {
        if (systemPM == null) {
            systemPM = new JarPersistentManager();
        }

        return systemPM;
    }

    public void setSystemTop(String systemTop) {
        this.systemTop = systemTop;
    }

    public String getSystemTop() {
        return systemTop;
    }

    public String getTemplateTop() {
        return templateTop;
    }

    public String getUserContentTop() {
        return getUserTop() + File.separatorChar + "users";
    }

    public String getUserName() {
        return dbConfig.getUserName();
    }

    public String getWebTop() {
        return webTop;
    }

    public void createDefault(WebContext pCtx) {
        dbConfig.createDefault(pCtx);

        if (getExternalBean() != null) {
            getExternalBean().createDefault(pCtx);
        }
    }

    /**
     * Loads configuration. This should be called only once when applicaiton
     * is loaded. It loads configuration and try to initialized the application.
     *
     * */
    public boolean load(String path) {
        boolean loaded = super.load(path);

        this.webTop = path;
        dbConfig.load(path);
        

        if (getExternalBean() != null) {
            getExternalBean().load(path);
        }
        return loaded;
    }

    /**
     * Saves configuration
     */
    public void update() {
        super.update();
        dbConfig.update();

        if (getExternalBean() != null) {
            getExternalBean().update();
        }
    }

    public void setGoogleDevKey(String googleDevKey) {
        this.googleDevKey = googleDevKey;
    }

    public String getGoogleDevKey() {
        return googleDevKey;
    }

    public void setIcon(String param) {
        this.icon = param;
    }

    public String getIcon() {
        return icon;
    }

    public Collection getManagedBeans() {
        return this.getChildren();
    }
}
